package android.Spider;

import java.util.ArrayList;
import java.util.List;

import net.idugic.dto.ProfileDTO;
import net.idugic.dto.QueryAnswerOptionDTO;
import net.idugic.dto.QueryDTO;
import net.idugic.dto.ThreadPostDTO;
import net.idugic.dto.TopicThreadDTO;
import net.idugic.rpc.socket.client.RPCClient;
import net.idugic.rpc.socket.common.RPCException;
import android.app.ApplicationContext;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.widget.Toast;

import com.google.android.gtalkservice.GTalkServiceConstants;
import com.google.android.gtalkservice.IGTalkService;
import com.google.android.gtalkservice.IGTalkSession;

public class SpiderListener extends Service implements Runnable
{
	/*
	 * Description of messages.
	 * Every message has to start with message request ID and GMail account of a sender.
	 */
	
	public static final String s_strReqID = "ReqID";
	public static final String s_strReqType = "ReqType";
	public static final String s_strWhat = "What";

	public static final String s_strReqQuestion = "ReqQuestion";
	public static final String s_strReqAnswer = "ReqAnswer";
	public static final String s_strReqMessage = "ReqMessage";
	
	public static final String s_strSender = "Sender";
	public static final String s_strOwner = "Owner";
	public static final String s_strMsg = "Msg";
	public static final String s_strOption = "Option";
	public static final String s_strFrom = "From";
	public static final String s_strTo = "To";
	public static final String s_strQuestionID = "QuestionID";
	public static final String s_strAllowForward = "AllowForward";
	
	public static final int s_nSendQuestion = 1;
	public static final int s_nXmppMsgArrived = 2;
	public static final int s_nSendAnswer = 3;
	public static final int s_nSubmitProfile = 4;
	public static final int s_nRequestInquiriesResults = 5;
	public static final int s_nDeleteInquiry = 6;
	public static final int s_nForwardQuestion = 7;
	public static final int s_nRequestTopicThreads = 8;
	public static final int s_nSubmitPost = 9;
	public static final int s_nCreateTopicThread = 10;
	public static final int s_nPrivateMessageSend = 11;
	public static final int s_nRequestProfiles = 12;
	
    @Override
    protected void onCreate()
    {
        Thread thr = new Thread(null, this, "SpiderListener");
        thr.start();
        
        // Ensures that we have a unique ID per user.
        s_idRequest = SpiderPreferences.Instance(this).GetRequestID();
        
        BindXmppService();
    }

    @Override
    protected void onStart(int startId, Bundle arguments)
    {
    	// If service handler is not created yet, wait until its created.
        while (m_srvHandler == null)
        {
            synchronized (this) {
                try { wait(100); }
                catch (InterruptedException e) {}
            }
        }

        if (arguments != null)
        {
            // Create and Send message to process arguments.
            Message msg = m_srvHandler.obtainMessage();
            int nWhat = arguments.getInt(s_strWhat, s_nXmppMsgArrived);
            msg.what = nWhat;
            msg.arg1 = startId;
            msg.obj = arguments;
            m_srvHandler.sendMessage(msg);
        }
    }

    @Override
    protected void onDestroy()
    {
        while (m_srvLooper == null)
        {
            synchronized (this)
            {
                try { wait(100); }
                catch (InterruptedException e) {}
            }
        }
        m_srvLooper.quit();
    }

	public void run()
	{
        Looper.prepare();

        m_srvLooper = Looper.myLooper();
        m_srvHandler = new ServiceHandler();

        Looper.loop();
	}

	public boolean IsXmppInitialized()
	{
		boolean bConnected = m_XmppSession != null;
		if (bConnected)
		{
			try {
				bConnected = m_XmppSession.isConnected();
			} catch (DeadObjectException e) {
				bConnected = false;
			}
		}
		
		return bConnected;
	}

	public boolean BindXmppService()
	{
        return bindService((new Intent()).setComponent(GTalkServiceConstants.GTALK_SERVICE_COMPONENT),
				m_XmppServiceConnection, 
				0);
	}

	public static void OnConnected()
	{
		int nSize = s_lstReceivers.size();
		for (int i = 0; i < nSize; ++i)
			s_lstReceivers.get(i).OnConnected();
	}

	public static void OnDisconnected()
	{
		int nSize = s_lstReceivers.size();
		for (int i = 0; i < nSize; ++i)
			s_lstReceivers.get(i).OnDisconnected();
	}

    private ServiceConnection m_XmppServiceConnection = new ServiceConnection()
    {
        public void onServiceConnected(ComponentName className, IBinder service)
        {
            IGTalkService xmppService = IGTalkService.Stub.asInterface(service);

            try {
                m_XmppSession = xmppService.getDefaultSession();
                if (m_XmppSession != null)
                {
                    UserName = SpiderListener.this.m_XmppSession.getUsername();
                    SpiderListener.OnConnected();
                }
                else
                {
                	Toast.makeText(SpiderListener.this, 
                			"There is no XMPP connection. " +
                			"Application features will be serously degraded!", 
                			Toast.LENGTH_LONG)
                			.show();
                }
            } 
            catch (DeadObjectException ex)
            {
            	m_XmppSession = null;
//            	UserName = new String();
            	SpiderListener.OnDisconnected();
                BindXmppService();
            }
        }

        public void onServiceDisconnected(ComponentName className)
        {
            m_XmppSession = null;
        	SpiderListener.OnDisconnected();
        }
    };

	public class SpiderBinder extends Binder
	{
		// Called only if you are initiating a question.
		public void SendQuestion(XmppConnection receiver, Questions.Question q)
		{
			q.m_strOwner = new String(UserName);
			q.m_idQuestion = s_idRequest + 1;
			SendQuestionComplete(receiver, q);			
		}
		
		// Called only if you are just forwarding a question. Then idQuestion has to be specified and it refers to the first contact in the list.
		private void SendQuestionComplete(XmppConnection receiver, Questions.Question q)
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nSendQuestion;
            msg.obj = q;

            m_srvHandler.sendMessage(msg);
		}
		
		public void SendAnswer(String strTo, long idQuestion, int nOption)
		{			
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nSendAnswer;
            msg.arg1 = (int)idQuestion;
            msg.arg2 = nOption;
            msg.obj = strTo;

            m_srvHandler.sendMessage(msg);
		}

		void SubmitProfile(ProfileUser usrProfile)
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nSubmitProfile;
            msg.obj = usrProfile;

            m_srvHandler.sendMessage(msg);
		}

		void RequestAllProfiles()
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nRequestProfiles;

            m_srvHandler.sendMessage(msg);
		}

		void RequestInquiriesResults()
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nRequestInquiriesResults;

            m_srvHandler.sendMessage(msg);
		}
		
		void DeleteInquiry(long idQuestion)
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nDeleteInquiry;
            msg.arg1 = (int)idQuestion;
            
            m_srvHandler.sendMessage(msg);
		}
		
		void ForwardQuestion(long idQuestion, ArrayList<String> lstTo)
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nForwardQuestion;
            msg.arg1 = (int)idQuestion;
            msg.obj = lstTo;
            
            m_srvHandler.handleMessage(msg);
		}

		void RequestThreads(int idTopic)
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nRequestTopicThreads;
            msg.arg1 = (int)idTopic;
            
            m_srvHandler.handleMessage(msg);
		}

		void SubmitPost(int idThread, String strText)
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nSubmitPost;
            msg.arg1 = (int)idThread;
            msg.obj = strText;
            
            m_srvHandler.handleMessage(msg);
		}

		void CreateTopicThread(int idTopic, String strTitle, String strText)
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nCreateTopicThread;
            msg.arg1 = (int)idTopic;
            ArrayList<String> lst = new ArrayList<String>(2);
            lst.add(strTitle);
            lst.add(strText);
            msg.obj = lst;
            
            m_srvHandler.handleMessage(msg);
		}
		
		void SendPrivateMessage(String strTo, String strText)
		{
            Message msg = m_srvHandler.obtainMessage();
            msg.what = s_nPrivateMessageSend;
            ArrayList<String> lst = new ArrayList<String>(2);
            lst.add(strTo);
            lst.add(strText);
            msg.obj = lst;
            
            m_srvHandler.handleMessage(msg);
		}

		public boolean IsInitialized() { return SpiderListener.this.IsXmppInitialized(); }
		
	};
	
	private void PutMessageHeader(Bundle bundle)
	{
		// Create a new request ID and store it to Preferences.
		SpiderPreferences.Instance(SpiderListener.this).SetRequestID(++s_idRequest);
		
		bundle.putString(s_strReqID, (new Long(s_idRequest)).toString());
		bundle.putString(s_strSender, UserName);
	}

	private synchronized boolean DispatchData(List<String> lstReceivers, Intent intent)
    {
    	boolean bResult = false;
    	if (m_XmppSession != null)
    	{
    		int nSize = lstReceivers.size();
    		for (int i = 0; i < nSize; ++i)
    		{
    			String strTo = lstReceivers.get(i) + "/android";		// This addition is only temporary to avoid problem with full JID.
        		try {
            		m_XmppSession.sendDataMessage(strTo, intent);
            		bResult = true;
        		}
        		catch(DeadObjectException ex)
        		{
        			m_XmppSession = null;
        			BindXmppService();
        			break;
        		}
    		}
    	}

		return bResult;
    }

	@Override
	public IBinder onBind(Intent intent) { return m_binder; }
	
	public static void Unregister(XmppConnection receiver)
	{
		int nLocation = 0;
		while (nLocation < s_lstReceivers.size())
		{
			if (s_lstReceivers.get(nLocation).equals(receiver))
			{
				s_lstReceivers.remove(nLocation);
				nLocation = -1;
			}
			
			++nLocation;
		}
	}
	
	private void OnQuestionReceived(Bundle question)
	{
		// Store the question
		long idQuestion = Long.parseLong(question.getString(s_strQuestionID));
		String strOwner = question.getString(s_strOwner);
		ArrayList<String> lstOptions = Serializer.BundleExtract(question, s_strOption);
		ArrayList<String> lstFrom = Serializer.BundleExtract(question, s_strFrom);
		ArrayList<String> lstTo = Serializer.BundleExtract(question, s_strTo);
		boolean bAllowForward = Boolean.parseBoolean(question.getString(s_strAllowForward));
		
		Questions q = Questions.Instance(this);
		q.AddQuestion(strOwner, idQuestion, question.getString(s_strMsg), lstOptions, lstFrom, lstTo, bAllowForward, true);
		q.Store();
		
		for (int i = 0; i < s_lstReceivers.size(); ++i)
		{
			int idRequest = Integer.parseInt(question.getString(s_strReqID));
			s_lstReceivers.get(i).OnServiceQuestionReceived(idRequest, idQuestion);
		}
	}
	
	public static void UpdateNotification(ApplicationContext ctx)
	{
		Questions q = Questions.Instance(ctx);
		int nUnansweredCount = q.GetUnansweredCount();
		PrivateMessages msgs = PrivateMessages.Instance(ctx);
		int nUnreadCount = msgs.GetUnreadCount();
		
    	NotificationManager notifier = (NotificationManager)ctx.getSystemService(NOTIFICATION_SERVICE);

    	int nPicture;
    	Intent intent;
    	String strShortDisplayText;
    	String strLongDisplayText;
    	if (nUnreadCount > 0 && nUnansweredCount > 0)
    	{
    		nPicture = R.drawable.spiderblue;
    		intent = new Intent(ctx, Broodmother.class);
    		strShortDisplayText = "You have new messages";
    		strLongDisplayText = "You have new private messages and inquiries";
    	}
    	else if (nUnreadCount == 0 && nUnansweredCount > 0)
    	{
    		nPicture = R.drawable.spidergreen;
    		intent = new Intent(ctx, PollReceive.class);
    		strShortDisplayText = "You have new inquiries";
    		strLongDisplayText = "You have new queries or polls";
    	}
    	else if (nUnreadCount > 0 && nUnansweredCount == 0)
    	{
    		nPicture = R.drawable.spideryellow;
    		intent = new Intent(ctx, Broodmother.class);
    		strShortDisplayText = "You have new messages";
    		strLongDisplayText = "You have new private messages";
    	}
    	else
    	{
    		nPicture = R.drawable.spiderblack;
    		intent = new Intent(ctx, Broodmother.class);
    		strShortDisplayText = "No new messages";
    		strLongDisplayText = "There are no new messages or inquiries";
    	}

    	notifier.notify(R.string.service_notification,
			new Notification(
				ctx,
				nPicture,
				strShortDisplayText,
				System.currentTimeMillis(),
				"Spider messages",
				strLongDisplayText,
				intent,
				R.drawable.homespider,
				"CyberNest",
				new Intent(ctx, Broodmother.class)
			)
    	);

	}

	private void OnAnswerReceived(Bundle answer)
	{
		Questions questions = Questions.Instance(this);
		
		int nOption = Integer.parseInt(answer.getString(s_strOption));
		long idQuestion = Long.parseLong(answer.getString(s_strQuestionID));
		String strSender = answer.getString(s_strSender);
		
		Questions.Question q = questions.GetQuestion(idQuestion);
		if (q != null)
		{
			q.AddAnswer(strSender, nOption);
			questions.Store();

			for (int i = 0; i < s_lstReceivers.size(); ++i)
			{
				s_lstReceivers.get(i).OnServiceAnswerReceived(idQuestion, strSender, nOption);
			}
		}
	}

	private void OnMessageReceived(Bundle msg)
	{
		String strFrom = msg.getString(s_strOwner);
		String strText = msg.getString(s_strMsg);

		PrivateMessages pm = PrivateMessages.Instance(this);
		int idMessage = pm.AddMessage(strFrom, strText);
		pm.Store();
		for (int i = 0; i < s_lstReceivers.size(); ++i)
		{
			s_lstReceivers.get(i).OnServiceMessageReceived(idMessage);
		}
	}
	
	public static void Register(XmppConnection receiver) { s_lstReceivers.add(receiver); }
	
    private final class ServiceHandler extends Handler
    {
        @SuppressWarnings("unchecked")
		@Override
        public void handleMessage(Message msg)
        {
        	switch (msg.what)
        	{
        	case s_nXmppMsgArrived:
	        	{
	                Bundle arguments = (Bundle)msg.obj;
	                String strReqType = arguments.getString(s_strReqType);
	                if (strReqType != null)
	                {
	                	// This is some our message since it has request type specified.
	                	if (strReqType.equals(s_strReqQuestion))
	                		SpiderListener.this.OnQuestionReceived(arguments);
	                	else if (strReqType.equals(s_strReqAnswer))
	                		SpiderListener.this.OnAnswerReceived(arguments);
	                	else if (strReqType.equals(s_strReqMessage))
	                		SpiderListener.this.OnMessageReceived(arguments);
	                }

	    			SpiderListener.UpdateNotification(SpiderListener.this);

	    			stopSelf(msg.arg1);
	        	}
        		break;
        	case s_nSendQuestion:
	        	{
	        		Questions.Question q = (Questions.Question)msg.obj;
	                
	        		if (m_rpcClient == null)
	        			m_rpcClient = RPCClient.getInstance();
	        		
	        		try {
	                    Integer queryId = (Integer)m_rpcClient.execute("QueryDAO.createQuery", 
	                    		q.m_strOwner, q.m_strMsg, q.m_lstOptions,
	                    		new Boolean(q.m_bAllowForward), q.m_lstTo);
	                    
	                    q.m_idQuestion = queryId.intValue();

		                Intent intent = new Intent(MessageReceiver.ACTION);

		        		Bundle question = new Bundle();
		        		PutMessageHeader(question);

		    			question.putString(s_strReqType, s_strReqQuestion);
		    			question.putString(s_strOwner, q.m_strOwner);
		    			question.putString(s_strQuestionID, (new Long(q.m_idQuestion)).toString());

		    			ArrayList<String> lstAddedFrom = new ArrayList<String>(q.m_lstFrom);
		    			lstAddedFrom.add(UserName);
		    			Serializer.AddToBundle(question, s_strFrom, lstAddedFrom);

		    			Serializer.AddToBundle(question, s_strTo, q.m_lstTo);

		    			question.putString(s_strMsg, q.m_strMsg);

		    			Serializer.AddToBundle(question, s_strOption, q.m_lstOptions);

		    			intent.putExtras(question);
		    			
		    			// Store the question
		    			Questions questions = Questions.Instance(SpiderListener.this);
		    			questions.AddQuestion(q);
		    			questions.Store();
		    			
		            	SpiderListener.this.DispatchData(q.m_lstTo, intent);
	        		}
	        		catch (RPCException e) {
	        			e.printStackTrace();
	        	    }
	        	}
	        	break;
        	case s_nSendAnswer:
	        	{
	        		long idQuestion = msg.arg1;
	        		int nOption = msg.arg2;
	        		String strTo = (String)msg.obj;
	        		
	        		if (m_rpcClient == null)
	        			m_rpcClient = RPCClient.getInstance();

                    try {
						m_rpcClient.execute("QueryDAO.answerQuery", UserName, new Integer((int)idQuestion), new Integer(nOption));
						
		                Intent intent = new Intent(MessageReceiver.ACTION);

		        		Bundle answer = new Bundle();
		    			PutMessageHeader(answer);

		    			answer.putString(s_strReqType, s_strReqAnswer);
		    			answer.putString(s_strQuestionID, (new Long(idQuestion)).toString());
		    			answer.putString(s_strOwner, strTo);
		    			answer.putString(s_strOption, (new Integer(nOption)).toString());
		    			
		    			intent.putExtras(answer);

		    			Questions q = Questions.Instance(SpiderListener.this);
		    			if (q != null)
		    			{
			    			q.AddAnswer(idQuestion, UserName, nOption);
			    			q.Store();
		    			}
		    			
		    			SpiderListener.UpdateNotification(SpiderListener.this);

		    			ArrayList<String> lstTo = new ArrayList<String>(1);
		    			lstTo.add(strTo);
		    			SpiderListener.this.DispatchData(lstTo, intent);
		    			
		    			for (int i = 0; i < s_lstReceivers.size(); ++i)
		    				s_lstReceivers.get(i).OnServiceAnswerSent(idQuestion);
					}
                    catch (RPCException e) {
						e.printStackTrace();
					}
                    
	        	}
	        	break;
        	case s_nSubmitProfile:
	        	{
	        		ProfileUser profile = (ProfileUser)msg.obj;
	        		profile.m_strGMail = UserName;
	        		
	        		SpiderPreferences pref = SpiderPreferences.Instance(SpiderListener.this);
	        		pref.SetUserFirstName(profile.m_strFirstName);
	        		pref.SetUserLastName(profile.m_strLastName);
	        		pref.SetPassword(profile.m_strPassword);
	        		pref.SetCountry(profile.m_nCountry);
	        		pref.SetInterests(profile.m_nInterests);
	        		pref.SetGender(profile.m_bMale);
	        		pref.SetTown(profile.m_strTown);
	        		pref.SetAvatar(profile.m_nAvatar);
	        		pref.SetOccupation(profile.m_nOccupation);
	        		
	        		if (m_rpcClient == null)
	        			m_rpcClient = RPCClient.getInstance();

                    try {
                    	//public Integer submitProfile(ProfileDTO profileDTO);
                    	m_rpcClient.execute("ProfileDAO.submitProfile", profile.toDTO());
					}
                    catch (RPCException e) {
						e.printStackTrace();
					}
	        	}
        		break;
        	case s_nRequestInquiriesResults:
	        	{
	        		if (UserName.length() == 0)
	        		{
	        			this.sendMessageDelayed(msg, 100);
	        		}
	        		else
	        		{
	        			Questions questions = Questions.Instance(SpiderListener.this);
	        			
		        		if (m_rpcClient == null)
		        			m_rpcClient = RPCClient.getInstance();
		        		
		        		try
		        		{
		        			@SuppressWarnings("unused")
							List<QueryDTO> lstQueryDto = (List<QueryDTO>)m_rpcClient.execute("QueryDAO.getActiveQueryList", UserName);
		        			
		        			ArrayList<Integer> lstQuestionID = new ArrayList<Integer>();				// Question IDs
		        			ArrayList<List<Integer>> lstOptionsCount = new ArrayList<List<Integer>>(); 	// Options for question ID in upper container
		        			
		        			// Now for all those queries I have to find all all options
		        			for (int i = 0; i < lstQueryDto.size(); ++i)
		        			{
		        				Integer idQuery = lstQueryDto.get(i).getId();
		        				lstQuestionID.add(idQuery);
		        				List<QueryAnswerOptionDTO> lstOptionsDto = (List<QueryAnswerOptionDTO>)m_rpcClient.execute("QueryDAO.getQueryAnswerOptionList", idQuery);
		        				
		        				// Add all options
		        				ArrayList<Integer> lstOptions = new ArrayList<Integer>(lstOptionsDto.size());
		        				ArrayList<String> lstOptionText = new ArrayList<String>(lstOptionsDto.size());
		        				for (int nOption = 0; nOption < lstOptionsDto.size(); ++nOption)
		        				{
		        					lstOptions.add(lstOptionsDto.get(nOption).getCount());
		        					lstOptionText.add(lstOptionsDto.get(nOption).getAnswer_text());
		        				}
		        				
		        				lstOptionsCount.add(lstOptions);
		        				
		        				Questions.Question q = questions.GetQuestion(idQuery.longValue());
		        				if (q == null)
		        				{
		        					// We don't have this question locally, so we need to fetch it from server
		        					// TODO: This is not absolutely complete. It should be improved as soon as server interface is improved.
		        					ArrayList<String> lstFrom = new ArrayList<String>(1);
		        					lstFrom.add(UserName);
		        					questions.AddQuestion(UserName, idQuery.longValue(), lstQueryDto.get(i).getQuery_text(), 
		        							lstOptionText, lstFrom, new ArrayList<String>(), true, false);		        					
		        				}
		        			}
		        			
		        			questions.Store();

			    			for (int i = 0; i < s_lstReceivers.size(); ++i)
			    				s_lstReceivers.get(i).OnServiceInquiriesResults(lstQuestionID, lstOptionsCount);
		        		}
	                    catch (RPCException e) {
							e.printStackTrace();
						}
	        		}
	        	}
	        	break;
        	case s_nDeleteInquiry:
        		{
	        		if (m_rpcClient == null)
	        			m_rpcClient = RPCClient.getInstance();
	        		
	        		try {
	        			m_rpcClient.execute("QueryDAO.deactivateQuery", new Integer(msg.arg1));
	        		}
                    catch (RPCException e) {
						e.printStackTrace();
					}
	        	}
        		break;
        	case s_nForwardQuestion:
	    		{
	        		if (m_rpcClient == null)
	        			m_rpcClient = RPCClient.getInstance();
	        		
	        		try {
	        			//public List<String> forwardQuery(Integer query, String forwarder_account, ArrayList<String> recipientList);
	        			// We can check if all recipients received, but I don't see it as important.
	        			m_rpcClient.execute("QueryDAO.forwardQuery", new Integer(msg.arg1), SpiderListener.UserName, (ArrayList<String>)msg.obj);
	        		}
	                catch (RPCException e) {
						e.printStackTrace();
					}
	        	}
        		break;
        	case s_nRequestTopicThreads:
        		if (m_rpcClient == null)
        			m_rpcClient = RPCClient.getInstance();
        		
        		ArrayList<TopicThread> lstThreads = new ArrayList<TopicThread>();
        		try {
        			//List<TopicThreadDTO> getTopicThreadList(Integer topic);
        			List<TopicThreadDTO> lstThreadsDTO = (List<TopicThreadDTO>)m_rpcClient.execute("TopicDAO.getTopicThreadList", new Integer(msg.arg1));
        			for (int i = 0; i < lstThreadsDTO.size(); ++i)
        			{
        				TopicThreadDTO thrd = lstThreadsDTO.get(i);
            			TopicThread thread = new TopicThread();
            			TopicThread.Issuer issuer = thread.CreateIssuer();
            			thread.m_idThread = thrd.getId();
            			thread.m_strThreadName = thrd.getTitle();
            			issuer.fromDTO(thrd);
            			thread.m_lstPosts.add(issuer);

            			// List<ThreadPostDTO> getThreadPostList(Integer thread);
        				List<ThreadPostDTO> lstPostsDTO = (List<ThreadPostDTO>)m_rpcClient.execute("TopicDAO.getThreadPostList", new Integer(thrd.getId()));
        				for (int nPost = 0; nPost < lstPostsDTO.size(); ++nPost)
        				{
        					ThreadPostDTO postDTO = lstPostsDTO.get(nPost);
        					TopicThread.Issuer sender = thread.CreateIssuer();
        					sender.fromDTO(postDTO);
                			thread.m_lstPosts.add(issuer);
        				}

            			lstThreads.add(thread);
        			}
        		}
				catch (RPCException e) {
					e.printStackTrace();
				}
 
       			for (int i = 0; i < s_lstReceivers.size(); ++i)
    				s_lstReceivers.get(i).OnTopicThreadsResults(lstThreads);

       			break;
        	case s_nRequestProfiles:
        		if (m_rpcClient == null)
        			m_rpcClient = RPCClient.getInstance();
        		
        		ArrayList<ProfileUser> lstProfiles = new ArrayList<ProfileUser>();
        		try {
        			List<ProfileDTO> lstDTO = (List<ProfileDTO>)m_rpcClient.execute("ProfileDAO.getAllProfiles");
        			for (int i = 0; i < lstDTO.size(); ++i)
        				lstProfiles.add(ProfileUser.toProfile(lstDTO.get(i)));
        		}
				catch (RPCException e) {
					e.printStackTrace();
				}

    			for (int i = 0; i < s_lstReceivers.size(); ++i)
    				s_lstReceivers.get(i).OnServiceProfilesReceived(lstProfiles);
    			
    			break;
        	case s_nSubmitPost:
	        	{
	        		try {
	        			m_rpcClient.execute("TopicDAO.submitPost", new Integer(msg.arg1), SpiderListener.UserName, (String)msg.obj);
	        		}
					catch (RPCException e) {
						e.printStackTrace();
					}
	        	}
        		break;
        	case s_nCreateTopicThread:
	        	{
	        		ArrayList<String> lst = (ArrayList<String>)msg.obj;
	        		String strTitle = lst.get(0);
	        		String strText = lst.get(1);
	
	        		try {
	        			m_rpcClient.execute("TopicDAO.createTopicThread", new Integer(msg.arg1), strTitle, strText, SpiderListener.UserName);
	        		}
					catch (RPCException e) {
						e.printStackTrace();
					}
	        	}
        		break;
        	case s_nPrivateMessageSend:
        		ArrayList<String> lst = (ArrayList<String>)msg.obj;
        		ArrayList<String> lstTo = new ArrayList<String>(1);
        		lstTo.add(lst.get(0));
        		String strText = lst.get(1);
        		
                Intent intent = new Intent(MessageReceiver.ACTION);

        		Bundle bundle = new Bundle();
    			PutMessageHeader(bundle);

    			bundle.putString(s_strReqType, s_strReqMessage);
    			bundle.putString(s_strOwner, SpiderListener.UserName);
    			bundle.putString(s_strMsg, strText);
    			
    			intent.putExtras(bundle);

    			SpiderListener.this.DispatchData(lstTo, intent);
            	
        		break;
        	}
        }
    };

    private volatile Looper 			m_srvLooper;
    private volatile ServiceHandler 	m_srvHandler = null;
    
    private static long					s_idRequest = 0;
    private SpiderBinder 				m_binder = new SpiderBinder();
    private IGTalkSession 				m_XmppSession = null;
    public static String 				UserName = new String();
    
    private RPCClient 					m_rpcClient = null;
    
	// All receivers. Need for notifications about connection.
    private static ArrayList<XmppConnection>	s_lstReceivers = new ArrayList<XmppConnection>();
}
